Skip to content

Method: Descriptor(URI, boolean)

1: /**
2: * Copyright (C) 2020 Czech Technical University in Prague
3: *
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: *
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.jopa.model.descriptors;
16:
17: import cz.cvut.kbss.jopa.model.metamodel.FieldSpecification;
18:
19: import java.lang.reflect.Field;
20: import java.net.URI;
21: import java.util.*;
22:
23: /**
24: * Defines base descriptor, which is used to specify context information for entities and their fields.
25: * <p>
26: * The descriptor hierarchy is a classical <b>Composite</b> pattern.
27: */
28: public abstract class Descriptor {
29:
30: protected final URI context;
31:
32: protected final boolean assertionsInSubjectContext;
33:
34: private String language;
35: private boolean hasLanguage;
36:
37: protected Descriptor() {
38: this(null);
39: }
40:
41: protected Descriptor(boolean assertionsInSubjectContext) {
42: this(null, assertionsInSubjectContext);
43: }
44:
45: protected Descriptor(URI context) {
46: this.context = context;
47: this.assertionsInSubjectContext = true;
48: }
49:
50: protected Descriptor(URI context, boolean assertionsInSubjectContext) {
51: this.context = context;
52: this.assertionsInSubjectContext = assertionsInSubjectContext;
53: }
54:
55: /**
56: * Gets context for this descriptor.
57: * <p>
58: * Note that the context URI may be {@code null}, meaning that the default context is referenced
59: *
60: * @return Context URI
61: */
62: public URI getContext() {
63: return context;
64: }
65:
66: /**
67: * Gets the language set for this descriptor.
68: *
69: * @return Language tag (e.g. en, cs), can be {@code null}, meaning any language is supported or the language tag
70: * has not been set (see {@link #hasLanguage()})
71: */
72: public String getLanguage() {
73: return language;
74: }
75:
76: /**
77: * Gets information about whether language tag has been set on this descriptor.
78: * <p>
79: * The language tag can be explicitly set to {@code null}, meaning any language is supported. This can be used to
80: * override PU-level language setting.
81: *
82: * @return {@code true} if a language tag has been set on this descriptor, {@code false} otherwise
83: */
84: public boolean hasLanguage() {
85: return hasLanguage;
86: }
87:
88: /**
89: * Sets language tag of this descriptor.
90: * <p>
91: * Applies to any possible sub-descriptors as well.
92: *
93: * @param languageTag The language tag to use, possibly {@code null}, meaning no language preference should be used
94: * @see #anyLanguage()
95: */
96: public Descriptor setLanguage(String languageTag) {
97: this.language = languageTag;
98: this.hasLanguage = true;
99: return this;
100: }
101:
102: /**
103: * Configures this descriptor to support any language tag (including no language tags).
104: * <p>
105: * This is useful for overriding previously set language tag expectations (either on PU level or parent descriptor
106: * level).
107: * <p>
108: * This does the same as calling {@link #setLanguage(String)} with {@code null} argument, but is more explicit.
109: */
110: public Descriptor anyLanguage() {
111: return setLanguage(null);
112: }
113:
114: /**
115: * Gets attribute descriptors specified in this descriptor.
116: *
117: * @return Unmodifiable view of attribute descriptors
118: */
119: public abstract Collection<Descriptor> getAttributeDescriptors();
120:
121: /**
122: * Gets descriptor for the specified attribute.
123: *
124: * @param attribute Entity attribute, as specified by the application metamodel
125: * @return Descriptor
126: * @throws IllegalArgumentException If the descriptor is not available
127: */
128: public abstract Descriptor getAttributeDescriptor(FieldSpecification<?, ?> attribute);
129:
130: /**
131: * Gets context in which the property assertion(s) of the specified attribute should be stored.
132: *
133: * @param attribute Entity attribute, as specified by the application model
134: * @return Context identifier
135: */
136: public abstract URI getAttributeContext(FieldSpecification<?, ?> attribute);
137:
138: /**
139: * Adds descriptor for the specified attribute.
140: *
141: * @param attribute The attribute to set descriptor for
142: * @param descriptor The descriptor to use
143: */
144: public abstract Descriptor addAttributeDescriptor(Field attribute, Descriptor descriptor);
145:
146: /**
147: * Adds repository context for the specified attribute.
148: * <p>
149: * This in effect means creating a descriptor for the specified field with the specified context.
150: *
151: * @param attribute The attribute to set context for
152: * @param context The context to set
153: * @see #addAttributeDescriptor(Field, Descriptor)
154: */
155: public abstract Descriptor addAttributeContext(Field attribute, URI context);
156:
157: /**
158: * Sets language to be used when working (retrieving, persisting) with values of the specified attribute.
159: * <p>
160: * Note that setting language in this manner will not have any effect on descriptors of the specified attribute
161: * previously retrieved from this descriptor.
162: *
163: * @param attribute The attribute concerned
164: * @param languageTag Language tag to use, possibly {@code null}
165: */
166: public abstract Descriptor setAttributeLanguage(Field attribute, String languageTag);
167:
168: /**
169: * Gets all contexts present in this descriptor.
170: * <p>
171: * If any of the descriptors specifies the default context, an empty set is returned.
172: * <p>
173: * In case of entity descriptor this means recursively asking all of its attributes for their context.
174: *
175: * @return Set of context URIs or an empty set, if the default one should be used
176: */
177: public Set<URI> getAllContexts() {
178: Set<URI> contexts = new HashSet<>();
179: contexts = getContextsInternal(contexts, new HashSet<>());
180: return contexts != null ? contexts : Collections.emptySet();
181: }
182:
183: /**
184: * Gets the contexts, discarding any already visited descriptors.
185: *
186: * @param contexts Contexts collected so far
187: * @param visited Visited descriptors
188: * @return Already visited contexts + those found in this descriptor
189: */
190: protected abstract Set<URI> getContextsInternal(Set<URI> contexts, Set<Descriptor> visited);
191:
192: /**
193: * Whether this descriptor can override parent descriptor's assertionsInSubjectContext setting.
194: */
195: protected boolean overridesAssertionsInSubjectContext() {
196: return false;
197: }
198:
199: /**
200: * Whether property assertion should be stored in the subject's context (default), or whether they should be stored
201: * together with the assertion value.
202: * <p>
203: * This applies to object references, as literal values are always stored in the specified context.
204: *
205: * @return Whether property assertion is stored in the subject context
206: */
207: public boolean areAssertionsInSubjectContext() {
208: return assertionsInSubjectContext;
209: }
210:
211: @Override
212: public boolean equals(Object o) {
213: if (this == o) {
214: return true;
215: }
216: if (!(o instanceof Descriptor)) {
217: return false;
218: }
219:
220: Descriptor that = (Descriptor) o;
221:
222: if (hasLanguage != that.hasLanguage) {
223: return false;
224: }
225: if (assertionsInSubjectContext != that.assertionsInSubjectContext) {
226: return false;
227: }
228: return Objects.equals(context, that.context) && Objects.equals(language, that.language);
229: }
230:
231: @Override
232: public int hashCode() {
233: int result = context != null ? context.hashCode() : 0;
234: result = 31 * result + (language != null ? language.hashCode() : 0);
235: result = 31 * result + (hasLanguage ? 1 : 0);
236: result = 31 * result + (assertionsInSubjectContext ? 1 : 0);
237: return result;
238: }
239:
240: @Override
241: public String toString() {
242: return context != null ? context.toString() : "default_context";
243: }
244: }